﻿using B.WMS.GoodsDto.Input;
using B.WMS.GoodsDto.Output;
using B.WMS.InWareHouseManagement;
using B.WMS.StandardReturn;
using B.WMS.WMSEntities.GoodsEntities;
using B.WMS.WMSEntities.Warehousety;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Plotly.NET;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.ObjectMapping;
using Aliyun.OSS;
using Microsoft.Extensions.Configuration;
using B.WMS.Good;

namespace B.WMS.Good
{
    public class GoodsAppService : ApplicationService, ITransientDependency, IGoodsAppService
    {
        private readonly IRepository<Goods, Guid> _goodsRepository;
        private readonly IRepository<Units, Guid> _unitsRepository;
        private readonly IRepository<Goodstype, Guid> _goodstypeRepository;
        private readonly IDistributedEventBus _distributedEventBus;
        private readonly IRepository<WVendor, Guid> _wvendorRepository;
        private readonly IRepository<WAllocate, Guid> _wAllocateRepository;
        private readonly IRepository<InWareHouseModel, Guid> _inWareHouseModelRepository;
        private readonly IRepository<Warehouse,Guid> _warehouseRepository;
        private readonly IRepository<Location, Guid> _locationRepository;
        private readonly IRepository<OutWareHouseModel, Guid> _outWareHouseModelRepository;
        private readonly IWebHostEnvironment _env;
        private readonly IConfiguration _configuration;
        private readonly OSSService _ossService;

        public GoodsAppService(
            IRepository<Goods, Guid> goodsRepository, 
            IRepository<Units, Guid> unitsRepository, 
            IRepository<Goodstype, Guid> goodstypeRepository, 
            IDistributedEventBus distributedEventBus, 
            IRepository<WVendor, Guid> wvendorRepository, 
            IWebHostEnvironment env, 
            IRepository<WAllocate, Guid> wAllocateRepository, 
            IRepository<InWareHouseModel, Guid> inWareHouseModelRepository, 
            IRepository<Warehouse, Guid> warehouseRepository, 
            IRepository<Location, Guid> locationRepository, 
            IRepository<OutWareHouseModel, Guid> outWareHouseModelRepository,
            IConfiguration configuration,
            OSSService ossService)
        {
            _goodsRepository = goodsRepository;
            _unitsRepository = unitsRepository;
            _goodstypeRepository = goodstypeRepository;
            _distributedEventBus = distributedEventBus;
            _wvendorRepository = wvendorRepository;
            _env = env;
            _wAllocateRepository = wAllocateRepository;
            _inWareHouseModelRepository = inWareHouseModelRepository;
            _warehouseRepository = warehouseRepository;
            _locationRepository = locationRepository;
            _outWareHouseModelRepository = outWareHouseModelRepository;
            _configuration = configuration;
            _ossService = ossService;
        }
        #region 货品信息
        /// <summary>
        /// 获取已入库货品列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<Goods>> GetGoods()
        {
            var goods = await _goodsRepository.GetListAsync(x=>x.Goodsstatus==2);
            return goods;
        }
        /// <summary>
        /// 获取商品列表
        /// </summary>
        /// <returns></returns>
        public async Task<ApiPaging<GoodsOutput>> GetGoodsList(string? goodsname, int? status, string? verdorid, DateTime? productiontime, DateTime? createtime, int Pageindex=1, int Pagesize=10)
        {
            var goods = await _goodsRepository.GetListAsync(x=>x.IsDelete==false);
            var unit = await _unitsRepository.GetListAsync();
            var type = await _goodstypeRepository.GetListAsync();
            var vendor = await _wvendorRepository.GetListAsync();

            var linq = from a in goods
                       join b in unit on a.GoodsUnitId equals b.Unitscoding
                       join c in type on a.Goodstypeid equals c.Goodstypecoding
                       join d in vendor on a.Vendorid equals d.WVendorcoding
                       select new GoodsOutput
                       {
                           Goodstypeid = a.GoodsUnitId,
                           GoodsUnitId = b.Unitscoding,
                           Createperson = a.Createperson,
                           Createtime = a.CreationTime,
                           Customerid = a.Customerid,
                           CustomerName = a.Customerid,
                           Earlywarning = a.Earlywarning,
                           Goodaimages = a.Goodaimages,
                           Goodsbarcodes = a.Goodsbarcodes,
                           Goodscoding = a.Goodscoding,
                           Goodsfile = a.Goodsfile,
                           Goodsname = a.Goodsname,
                           Goodsspecifications = a.Goodsspecifications,
                           Goodsstatus = a.Goodsstatus,
                           GoodstyoeName = c.WGoodstypename,
                           GoodsUnitName = b.UnitName,
                           Num = a.Num,
                           Inventoryprice = a.Inventoryprice,
                           Retrievalprice = a.Retrievalprice,
                           Shelflife = a.Shelflife,
                           Storageprice = a.Storageprice,
                           Updatetime = a.Updatetime,
                           Vendorid = a.Vendorid,
                           VendorName = d.WVendorname,
                            ProductionTime = a.ProductionTime,
                       };

            if (!string.IsNullOrEmpty(goodsname))
            {
                linq = linq.Where(a => a.Goodsname.Contains(goodsname));
            }
            if (status != null)
            {
                linq = linq.Where(a => a.Goodsstatus == status);
            }
            if (!string.IsNullOrEmpty(verdorid))
            {
                linq= linq.Where(a => a.Vendorid == verdorid);
            }
            if (productiontime != null)
            {
                linq = linq.Where(a => a.ProductionTime >=productiontime && a.ProductionTime < productiontime.Value.AddDays(1));
            }
            if (createtime != null)
            {
                linq = linq.Where(a => a.Createtime>=createtime && a.Createtime< createtime.Value.AddDays(1));
            }
            var count= linq.Count();
            var pagecount=(int)Math.Ceiling((count *1.0/Pagesize));
            var data = linq.OrderByDescending(x => x.Createtime).Skip((Pageindex - 1) *Pagesize).Take(Pagesize).ToList();
            return new ApiPaging<GoodsOutput>()
            {
                 Message="获取成功",
                  PageDatas=data,
                   TotalPage=pagecount,
                    TotalData=count,   
            };

        }
        /// <summary>
        /// 新增货品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<CreateGoodsInput> CreateGoods(CreateGoodsInput input)
        {
            
            input.Goodsstatus = 1;
            input.Createtime = DateTime.Now;
            input.Inventoryprice= input.Storageprice * input.Num;//库存总金额=库存数量*入库价格
            input.Goodscoding = AutoCode.AutoCode.GetCode("Gd").Result.ResultData;
            var goods=ObjectMapper.Map<CreateGoodsInput, Goods>(input);
            await _goodsRepository.InsertAsync(goods);
            return input;
        }
        /// <summary>
        /// 删除货品
        /// </summary>
        /// <param name="goodscoding"></param>
        /// <returns></returns>
        public async Task<int> DeleteGoods(string id)
        {
            var goods = await _goodsRepository.GetAsync(x=>x.Goodscoding==id);
            goods.IsDelete=true;
            var a= _goodsRepository.UpdateAsync(goods);
            if (a!=null)
            {
                return 1;
            }
            else
            {
                return 0;
            }
            
        }
        /// <summary>
        /// 获取货品详情
        /// </summary>
        /// <param name="coding"></param>
        /// <returns></returns>
        public async Task<Goods> GetGoodsDto(string coding)
        {
            return await _goodsRepository.GetAsync(x=>x.Goodscoding==coding);
            //var goods= await _goodsRepository.GetAsync(x=>x.Goodscoding==coding);
            //var unit= await _unitsRepository.GetAsync(x=>x.Unitscoding==goods.GoodsUnitId);
            //var type=await _goodstypeRepository.GetAsync(x=>x.Goodstypecoding==goods.Goodstypeid);
            //var wvendor=await _wvendorRepository.GetAsync(x=>x.WVendorcoding==goods.Vendorid);
            //var output = new GetGoodsDto
            //{
            //    Goodscoding = goods.Goodscoding,
            //    Goodsname = goods.Goodsname,
            //    Goodsstatus = goods.Goodsstatus,
            //    Goodstypeid = goods.Goodstypeid,
            //    CustomerName = goods.Customerid,
            //    GoodstyoeName = type.WGoodstypename,
            //    GoodsUnitName = unit.UnitName,
            //    VendorName = wvendor.WVendorname,
            //    Goodsspecifications = goods.Goodsspecifications,
            //    GoodsUnitId = goods.GoodsUnitId,
            //    Goodsbarcodes = goods.Goodsbarcodes,
            //    Customerid = goods.Customerid,
            //    Vendorid = goods.Vendorid,
            //    Storageprice = goods.Storageprice,
            //    Createperson = goods.Createperson,
            //    Createtime = goods.Createtime,
            //    Earlywarning = goods.Earlywarning,
            //    Goodaimages = goods.Goodaimages,
            //    Goodsfile = goods.Goodsfile,
            //    Inventory = goods.Inventory,
            //    Inventoryprice = goods.Inventoryprice,
            //    Retrievalprice = goods.Retrievalprice,
            //    Shelflife = goods.Shelflife,
            //    Updatetime = goods.Updatetime,
            //      ProductionTime = goods.ProductionTime,
            //};
            //return output;
        }
        /// <summary>
        /// 修改货品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<int> UpdateGoods(CreateGoodsInput input)
        {
            var goodsDesc = await GetGoodsDto(input.Goodscoding);
            var goods = ObjectMapper.Map(input,goodsDesc);
            goods.Updatetime = DateTime.Now;
            var isgoods= await  _goodsRepository.UpdateAsync(goods);
            if (isgoods != null)
            {
                return  1;
            }
            else
            {
                return 0;
            }
        }
        #endregion
        #region 货品单位
        /// <summary>
        /// 新增货品单位
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<CreateUnitDto> CreateUnit(CreateUnitInput input)
        {
            var unit = ObjectMapper.Map<CreateUnitInput, Units>(input);
            unit.Unitscoding= AutoCode.AutoCode.GetCode("Ut").Result.ResultData;
            await _unitsRepository.InsertAsync(unit);
            return ObjectMapper.Map<Units, CreateUnitDto>(unit);
        }
        /// <summary>
        /// 获取货品单位
        /// </summary>
        /// <returns></returns>
        public async Task<List<Units>> GetGoodsUnitList()
        {
            return await _unitsRepository.GetListAsync();
        }
        #endregion
        #region 货品类型
        /// <summary>
        /// 新增货品类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<CreateGoodsTypeDto> CreateGoodsType(CreateGoodsTypeInput input)
        {
            var type = ObjectMapper.Map<CreateGoodsTypeInput, Goodstype>(input);
            type.Goodstypecoding= AutoCode.AutoCode.GetCode("Gt").Result.ResultData;
            await _goodstypeRepository.InsertAsync(type);
            return ObjectMapper.Map<Goodstype, CreateGoodsTypeDto>(type);
        }
        /// <summary>
        /// 获取货品类型
        /// </summary>
        /// <returns></returns>
        public async Task<List<Goodstype>> GetGoodsTypeList()
        {
            return await _goodstypeRepository.GetListAsync();
        }
        #endregion
        #region 供应商信息
        /// <summary>
        /// 新增供应商
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<int> CreateWVendor(CreateWVendorInput input)
        {
            //分布式事务
            using (var scope = new TransactionScope())
            {
                try
                {
                    input.WVendorcoding = AutoCode.AutoCode.GetCode("VD").Result.ResultData;
                    var goods = new Goods()
                    {
                        Goodsname = input.WVendorGoods,
                        Vendorid = input.WVendorcoding,
                        Createtime = DateTime.Now,
                        Goodsstatus = 1,
                        Goodscoding = AutoCode.AutoCode.GetCode("Gd").Result.ResultData,
                        IsDelete = false,
                        Storageprice = input.WVendorMoney,
                        
                        Inventoryprice = input.WVendorMoney * input.WVendorCount,
                         ConcurrencyStamp= Guid.NewGuid().ToString(),
                          Createperson= "1",
                           CreationTime= DateTime.Now,
                           Updatetime=DateTime.Now,
                             Customerid= "1",
                               Earlywarning= "0",
                                Goodaimages=" ",
                                 Goodsbarcodes=" ",
                                  Goodsfile=" ",
                                   Goodsspecifications=" ",
                                     Goodstypeid= "0",
                                       GoodsUnitId= "0",
                                        ProductionTime= DateTime.Now,
                                         Retrievalprice=0,
                                          Shelflife=0,
                              LastModificationTime=DateTime.Now
                    };
                    var data = ObjectMapper.Map<CreateWVendorInput, WVendor>(input);
                    var vendor = await _wvendorRepository.InsertAsync(data);
                    var good = _goodsRepository.InsertAsync(goods);

                    if (good != null && vendor != null)
                    {
                        scope.Complete();//提交事务
                    }
                    return 1;
                }
                catch (Exception)
                {

                    throw;
                }
            };
        }
        /// <summary>
        /// 获取供应商列表
        /// </summary>
        /// <returns></returns>
        public Task<List<WVendor>> GetWVendors()
        {
            return _wvendorRepository.GetListAsync();
        }
        #endregion
        #region 调拨
        /// <summary>
        /// 新增调拨
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<int> CreateAllocate(CreateAllocateInput input)
        {
            //添加调拨表明细
            var goods= await _goodsRepository.GetAsync(x=>x.Goodscoding==input.Goodscoding);
            input.WAllocatecoding= AutoCode.AutoCode.GetCode("Al").Result.ResultData;
            input.GoodsName=goods.Goodsname;
            //所在仓库以及库位
            var WarehouseNoOutName =await _warehouseRepository.GetAsync(x=>x.WarehouseNo==input.WarehouseNoOut);
            input.WarehouseNoOutName= WarehouseNoOutName.Warename;
            var locationout =await _locationRepository.GetAsync(x=>x.LocationNo==input.LocationNoOut);
            input.LocationNoOutName = locationout.LocationName;
            var warehouin=await _warehouseRepository.GetAsync(x=>x.WarehouseNo==input.WarehouseNoIn);
            input.WarehouseNoInName=warehouin.Warename;
            var loactionin=await _locationRepository.GetAsync(x=>x.LocationNo==input.LocationNoIn);
            input.LocationNoInName=loactionin.LocationName;
            input.WAllocatetime= DateTime.Now;
            var allocate = ObjectMapper.Map<CreateAllocateInput,WAllocate>(input);
            var a= _wAllocateRepository.InsertAsync(allocate);
            //减少仓库库存
            var warehouse=await _warehouseRepository.GetAsync(x=>x.WarehouseNo==input.WarehouseNoOut);
            warehouse.Capacity -= input.Num;
            var b= _warehouseRepository.UpdateAsync(warehouse);
            //增加仓库库存
            var warehousin=await _warehouseRepository.GetAsync(x=>x.WarehouseNo==input.WarehouseNoIn);
            warehousin.Capacity += input.Num;
            var c= _warehouseRepository.UpdateAsync(warehousin);
            //location.
            if (a != null && b != null && c != null)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        /// <summary>
        /// 获取调拨列表
        /// </summary>
        /// <returns></returns>
        public  async Task<ApiPaging<WAllocate>> GetWAllocates(string? reason, DateTime? Alldatetime, int Pageindex = 1, int Pagesize = 10)
        {
            var wallocates =await  _wAllocateRepository.GetListAsync();
            if (reason != null)
            {
                wallocates = wallocates.Where(x => x.Reason.Contains(reason)).ToList();
            }
            if (Alldatetime != null)
            {
                wallocates = wallocates.Where(a => a.WAllocatetime >= Alldatetime && a.WAllocatetime < Alldatetime.Value.AddDays(1)).ToList();
            }
            var count = wallocates.Count();
            var pagecount = (int)Math.Ceiling((count * 1.0 / Pagesize));
            var data = wallocates.OrderByDescending(x => x.WAllocatetime).Skip((Pageindex - 1) * Pagesize).Take(Pagesize).ToList();
            return new ApiPaging<WAllocate>()
            {
                Message = "获取成功",
                PageDatas = data,
                TotalPage = pagecount,
                TotalData = count,
            };
        }
        /// <summary>
        /// 获取货品所在仓库以及库位
        /// </summary>
        /// <param name="goodscoding"></param>
        /// <returns></returns>
        public async Task<WarehouseLocationOutput> GetWarehouseLocation(string goodscoding)
        {
            var warehouseinfo =await _inWareHouseModelRepository.GetAsync(x => x.Relationordernum == goodscoding);
            var wareshousename=await _warehouseRepository.GetAsync(x => x.WarehouseNo == warehouseinfo.WarehouseId);
            var warehouseLocationname=await _locationRepository.GetAsync(x => x.LocationNo ==warehouseinfo.LocationNo);
                return new WarehouseLocationOutput()
                {
                    WarehouseLocationNo = warehouseinfo.LocationNo,
                    WarehouseNo = wareshousename.WarehouseNo,
                    //WarehouseName = wareshousename.Warename,
                    //WarehouseLocation = warehouseLocationname.LocationName,
                };

        }
        #endregion

        #region 预测功能
        /// <summary>
        /// 获取商品需求预测
        /// </summary>
        /// <param name="input">预测输入参数</param>
        /// <returns>预测结果</returns>
        public async Task<PredictionResultDto> GetGoodsPrediction(PredictionInputDto input)
        {
            // 创建ML模型实例
            var mlModel = new MLModel(
                _goodsRepository,
                _inWareHouseModelRepository,
                _outWareHouseModelRepository);

            // 调用ML模型进行预测
            return await mlModel.GetGoodsPrediction(input);
        }
        #endregion













        /// <summary>
        /// 上传图片/文件到阿里云OSS
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public async Task<string> Upload(IFormFile file)
        {
            try
            {
                if (_ossService == null)
                {
                    throw new InvalidOperationException("OSS服务未初始化，请检查配置");
                }

                // 使用OSS服务上传文件
                return await _ossService.UploadFileAsync(file, "goods");
            }
            catch (Exception ex)
            {
                // 记录错误日志
                Console.WriteLine($"文件上传失败：{ex.Message}");
                throw new Exception($"文件上传失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除OSS中的文件
        /// </summary>
        /// <param name="fileUrl">文件URL</param>
        /// <returns></returns>
        public async Task<bool> DeleteFile(string fileUrl)
        {
            try
            {
                if (_ossService == null)
                {
                    return false;
                }

                return await _ossService.DeleteFileAsync(fileUrl);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"文件删除失败：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 批量上传文件
        /// </summary>
        /// <param name="files">文件列表</param>
        /// <returns>上传结果列表</returns>
        public async Task<List<UploadResult>> UploadMultiple(IFormFileCollection files)
        {
            if (_ossService == null)
            {
                throw new InvalidOperationException("OSS服务未初始化，请检查配置");
            }

            return await _ossService.UploadMultipleFilesAsync(files, "goods");
        }

        ///// <summary>
        ///// 导出
        ///// </summary>
        ///// <returns></returns>
        //public async string Export()
        //{
        //    var goods =await _goodsRepository.GetListAsync();
        //    IWorkbook workbook = new XSSFWorkbook();
        //    ISheet sheet = workbook.CreateSheet("仓库信息");
        //    // 添加表头
        //    IRow headerRow = sheet.CreateRow(0);
        //    headerRow.CreateCell(0).SetCellValue("货品编码");
        //    headerRow.CreateCell(1).SetCellValue("货品名称");
        //    headerRow.CreateCell(2).SetCellValue("货品状态");
        //    headerRow.CreateCell(3).SetCellValue("货品类型编号");
        //    headerRow.CreateCell(4).SetCellValue("生产日期");
        //    headerRow.CreateCell(5).SetCellValue("规格型号");
        //    headerRow.CreateCell(6).SetCellValue("单位");
        //    headerRow.CreateCell(7).SetCellValue("条码");
        //    headerRow.CreateCell(8).SetCellValue("客户编号");
        //    headerRow.CreateCell(9).SetCellValue("供应商编号");
        //    headerRow.CreateCell(10).SetCellValue("数量");
           
        //    headerRow.CreateCell(11).SetCellValue("库存");
            
        //    headerRow.CreateCell(12).SetCellValue("保质期");

        //    // 添加数据
        //    for (int i = 0; i < goods.Count; i++)
        //    {
        //        var w = goods[i];
        //        IRow row = sheet.CreateRow(i + 1);
        //        row.CreateCell(0).SetCellValue(w.Goodscoding);
        //        row.CreateCell(1).SetCellValue(w.Goodsname);
        //        row.CreateCell(2).SetCellValue(w.Goodsstatus);
        //        row.CreateCell(3).SetCellValue(w.Goodstypeid);
        //        row.CreateCell(4).SetCellValue(w.ProductionTime);
        //        row.CreateCell(5).SetCellValue(w.Goodsspecifications);
        //        row.CreateCell(6).SetCellValue(w.GoodsUnitId);
        //        row.CreateCell(7).SetCellValue(w.Goodsbarcodes);
        //        row.CreateCell(8).SetCellValue(w.Customerid);
        //        row.CreateCell(9).SetCellValue(w.Vendorid);
        //        row.CreateCell(10).SetCellValue(w.Num);
        //        row.CreateCell(11).SetCellValue(w.Inventory);
        //        row.CreateCell(12).SetCellValue(w.Shelflife);
        //    }
        //    using (var ms = new MemoryStream())
        //    {
        //        workbook.Write(ms, leaveOpen: true);
        //        ms.Position = 0;
        //        return   ok(ms.ToArray(),"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","仓库信息.xlsx");
             
        //    }
        //}
    }
}
